#pragma once

#include <boost/signals2/signal.hpp>
#include <memory>
#include <boost/thread.hpp>
#include <iostream>
#include "data_struct/base/EventBase.h"

namespace behavior_controller {
template<typename Derived, typename Mod>
class Cloner {
public:
    template<typename Evt>
    void Call(Mod &mod, const std::shared_ptr<Evt> &evt_ptr) {
        ProcessEvent(mod, *evt_ptr);
    }

private:
    template<typename Evt>
    void ProcessEvent(Mod &mod, const Evt &evt) {
        EventGuard<Evt> g(evt);
        ((Derived *) this)->ProcessEvent(mod, evt);
    }
};

template<typename Mod, typename Evt>
class FunctionCloner : public Cloner<FunctionCloner<Mod, Evt>, Mod> {
public:
    typedef std::function<void(Mod *)> Function;

    FunctionCloner(Function &&func) : func_(std::forward<Function>(func)) {}

    void ProcessEvent(Mod &mod, const Evt &) { func_(&mod); }

private:
    Function func_;
};

template<typename Mod, typename Evt>
class FunctionEventFunctor : public Cloner<FunctionEventFunctor<Mod, Evt>, Mod> {
public:
    typedef std::function<void(Mod *, const Evt &)> Function;

    FunctionEventFunctor(Function &&func) : func_(std::forward<Function>(func)) {
    }

    void ProcessEvent(Mod &mod, const Evt &evt) { func_(&mod, evt); }

private:
    Function func_;
};

} // namespace behavior_controller
